/**
 * Copyright 2008 - 2009 Pro-Netics S.P.A.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package it.pronetics.madstore.hatom.alfresco.web.bean;

import it.pronetics.madstore.hatom.alfresco.util.HAtomDialogUtils;
import it.pronetics.madstore.hatom.alfresco.util.SelectItemUtils;
import it.pronetics.madstore.hatom.alfresco.util.XomUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;

import nu.xom.Element;
import nu.xom.Node;

import org.alfresco.web.bean.dialog.BaseDialogBean;

/**
 * Bean implementation for the "Update hEntry" dialog
 * 
 * @author Salvatore Incandela
 * 
 */

public class UpdatehEntryDialog extends BaseDialogBean {

	private AddhAtomXslDialog microformatsHAtom;
	private HEntryBean updatedEntry;
	private Map<String, Element> id2Elements = new TreeMap<String, Element>();
	private List<SelectItem> xslSelects = new ArrayList<SelectItem>();

	private String entryTitle;
	private String entrySummary;
	private String entryContent;
	private String entryAuthor;
	private String entryUpdated;
	private String entryName;

	private Element rootEntry;
	private String rootAddress;

	private boolean isModified = false;

	@Override
	public void init(Map<String, String> parameters) {
		super.init(parameters);
		this.clear();
		this.updatedEntry = new HEntryBean(this.microformatsHAtom
				.getEntryToUpdate());
		this.setEntryName(this.updatedEntry.getName());
		this.setEntryTitle(this.updatedEntry.getTitle());
		this.setEntrySummary(this.updatedEntry.getSummary());
		this.setEntryContent(this.updatedEntry.getContent());
		this.setEntryUpdated(this.updatedEntry.getUpdated());
		this.setEntryAuthor(this.updatedEntry.getAuthor());
		this.xslSelects.add(new SelectItem(SelectItemUtils.NOT_SELECTED));
		this.rootEntry = this.microformatsHAtom.getId2Elements().get(
				this.updatedEntry.getName());
		this.rootAddress = SelectItemUtils.getAddress(this.rootEntry);
		Node rootEntryCopy = rootEntry.copy();
		HEntryBean entry = new HEntryBean();
		retrieveAndStoreHentryOnCopy(rootEntryCopy, entry, this.id2Elements);
		List<Element> propertiesToDelete = HAtomDialogUtils.getProperties(
				this.updatedEntry, id2Elements);
		XomUtils.deleteElements(propertiesToDelete);
		retrieveXslSelectsOnCopy(rootEntryCopy);
	}

	@Override
	protected String finishImpl(FacesContext context, String outcome)
			throws Exception {
		this.id2Elements.clear();
		HEntryBean entry = new HEntryBean();
		HAtomDialogUtils.retrieveAndStoreHentry(rootEntry, entry,
				this.id2Elements);
		List<Element> propertiesToDelete = HAtomDialogUtils.getProperties(
				entry, id2Elements);
		XomUtils.deleteElements(propertiesToDelete);
		retrieveXslSelects(rootEntry);
		HAtomDialogUtils.addMicroformatsHAtomToOneNode(XomUtils.SPAN,
				getEntryTitle(), HAtomDialogUtils.HATOM_TITLE, id2Elements);
		HAtomDialogUtils.addMicroformatsHAtomToOneNode(XomUtils.SPAN,
				getEntrySummary(), HAtomDialogUtils.HATOM_SUMMARY, id2Elements);
		HAtomDialogUtils.addMicroformatsHAtomToOneNode(XomUtils.SPAN,
				getEntryContent(), HAtomDialogUtils.HATOM_CONTENT, id2Elements);
		HAtomDialogUtils.addMicroformatsHAtomToOneNode(XomUtils.SPAN,
				getEntryUpdated(), HAtomDialogUtils.HATOM_UPDATED, id2Elements);
		HAtomDialogUtils.addMicroformatsHAtomToOneNode(XomUtils.ADDRESS,
				getEntryAuthor(), HAtomDialogUtils.HATOM_AUTHOR, id2Elements);
		this.microformatsHAtom.getId2Elements().remove(this.entryName);
		this.microformatsHAtom.getId2Elements().remove(this.entryAuthor);
		this.microformatsHAtom.getId2Elements().remove(this.entryContent);
		this.microformatsHAtom.getId2Elements().remove(this.entrySummary);
		this.microformatsHAtom.getId2Elements().remove(this.entryTitle);
		this.microformatsHAtom.getId2Elements().remove(this.entryUpdated);
		HEntryBean entryJustUpdated = new HEntryBean();
		HAtomDialogUtils.retrieveAndStoreHentry(rootEntry, entryJustUpdated,
				this.id2Elements);
		this.microformatsHAtom.getId2Elements().putAll(this.id2Elements);
		this.microformatsHAtom.getId2Elements().put(
				this.updatedEntry.getName(), rootEntry);
		this.microformatsHAtom.getAddedHEntries().remove(
				this.microformatsHAtom.getEntryToUpdate());
		this.microformatsHAtom.getAddedHEntries().add(this.updatedEntry);
		return "dialog:close";
	}

	@Override
	public boolean getFinishButtonDisabled() {
		return !this.isModified || isConflict() || !isRequiredFieldsDefined();
	}

	@Override
	public String cancel() {
		this.microformatsHAtom.setUpdatedAnAddedHEntry(false);
		return super.cancel();
	}

	/**
	 * This method clears the state of this bean.
	 */

	private void clear() {
		this.id2Elements.clear();
		this.xslSelects.clear();
		this.isModified = false;
	}

	private void retrieveXslSelects(Node node) {
		if (node instanceof Element) {
			Element element = (Element) node;
			String nameTag = element.getQualifiedName();
			if (nameTag.equals("xsl:value-of")) {
				SelectItem item = SelectItemUtils.getSelectItem(element);
				this.id2Elements.put((String) item.getValue(), element);
				this.xslSelects.add(item);
			}
		}
		for (int i = 0; i < node.getChildCount(); i++) {
			Node child = node.getChild(i);
			retrieveXslSelects(child);
		}
	}

	private void retrieveXslSelectsOnCopy(Node node) {
		if (node instanceof Element) {
			Element element = (Element) node;
			String nameTag = element.getQualifiedName();
			if (nameTag.equals("xsl:value-of")) {
				SelectItem item = SelectItemUtils.getSelectItem(element,
						this.rootAddress);
				this.id2Elements.put((String) item.getValue(), element);
				this.xslSelects.add(item);
			}
		}
		for (int i = 0; i < node.getChildCount(); i++) {
			Node child = node.getChild(i);
			retrieveXslSelectsOnCopy(child);
		}
	}

	private void retrieveAndStoreHentryOnCopy(Node node, HEntryBean entry,
			Map<String, Element> id2Elements) {
		if (node instanceof Element) {
			buildHEntryBeanOnCopy(node, entry, id2Elements);
		}
		for (int i = 0; i < node.getChildCount(); i++) {
			retrieveAndStoreHentryOnCopy(node.getChild(i), entry, id2Elements);
		}
	}

	private void buildHEntryBeanOnCopy(Node child, HEntryBean entry,
			Map<String, Element> id2Elements) {
		String valueClass;
		Element elementChild = (Element) child;
		valueClass = elementChild.getAttributeValue("class");
		if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_TITLE)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild,
					this.rootAddress);
			entry.setTitle(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		} else if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_AUTHOR)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild,
					this.rootAddress);
			entry.setAuthor(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		} else if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_CONTENT)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild,
					this.rootAddress);
			entry.setContent(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		} else if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_SUMMARY)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild,
					this.rootAddress);
			entry.setSummary(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		} else if (valueClass != null
				&& valueClass.equals(HAtomDialogUtils.HATOM_UPDATED)) {
			String valueSelect = SelectItemUtils.getValueSelect(elementChild,
					this.rootAddress);
			entry.setUpdated(valueSelect);
			id2Elements.put(valueSelect, elementChild);
		}
	}

	/**
	 * This Action is used to enable the updating of the current hEntry
	 * 
	 * @param event
	 */

	public synchronized void updateHEntryTemp(final ActionEvent event) {
		if (!isConflict() && isRequiredFieldsDefined()) {
			this.isModified = true;
			this.updatedEntry.update(entryTitle, entrySummary, entryContent,
					entryUpdated, entryAuthor);
		}
	}

	/**
	 * This method checks if there are different hAtom properties with same
	 * value.
	 * 
	 * @return true if there are different hAtom properties with same value.
	 */

	public boolean isConflict() {
		List<String> listString = new ArrayList<String>();
		listString.add(entryAuthor);
		listString.add(entryContent);
		listString.add(entrySummary);
		listString.add(entryTitle);
		listString.add(entryUpdated);
		for (String property : listString) {
			int occur = HAtomDialogUtils.occurInList(property, listString);
			if (occur > 1) {
				return true;
			}
		}
		return false;
	}

	/**
	 * This method checks if the required fields are set.
	 * 
	 * @return
	 */

	public boolean isRequiredFieldsDefined() {
		if (this.entryTitle != null && this.entryUpdated != null) {
			return !this.entryTitle.equals(SelectItemUtils.NOT_SELECTED)
					&& !this.entryUpdated.equals(SelectItemUtils.NOT_SELECTED);
		} else if (this.entryTitle == null && this.entryUpdated != null) {
			return !this.entryUpdated.equals(SelectItemUtils.NOT_SELECTED);
		} else if (this.entryTitle != null && this.entryUpdated == null) {
			return !this.entryTitle.equals(SelectItemUtils.NOT_SELECTED);
		} else
			return true;
	}

	public AddhAtomXslDialog getMicroformatsHAtom() {
		return microformatsHAtom;
	}

	public void setMicroformatsHAtom(AddhAtomXslDialog microformatsHAtom) {
		this.microformatsHAtom = microformatsHAtom;
	}

	public HEntryBean getEntryToUpdate() {
		return updatedEntry;
	}

	public void setEntryToUpdate(HEntryBean entryToUpdate) {
		this.updatedEntry = entryToUpdate;
	}

	public List<SelectItem> getXslSelectsForThisEntry() {
		return xslSelects;
	}

	public void setXslSelectsForThisEntry(
			List<SelectItem> xslSelectsForThisEntry) {
		this.xslSelects = xslSelectsForThisEntry;
	}

	public String getEntryTitle() {
		return entryTitle;
	}

	public void setEntryTitle(String entryTitle) {
		this.entryTitle = entryTitle;
	}

	public String getEntrySummary() {
		return entrySummary;
	}

	public void setEntrySummary(String entrySummary) {
		this.entrySummary = entrySummary;
	}

	public String getEntryContent() {
		return entryContent;
	}

	public void setEntryContent(String entryContent) {
		this.entryContent = entryContent;
	}

	public String getEntryAuthor() {
		return entryAuthor;
	}

	public void setEntryAuthor(String entryAuthor) {
		this.entryAuthor = entryAuthor;
	}

	public String getEntryUpdated() {
		return entryUpdated;
	}

	public void setEntryUpdated(String entryUpdated) {
		this.entryUpdated = entryUpdated;
	}

	public String getEntryName() {
		return entryName;
	}

	public void setEntryName(String entryName) {
		this.entryName = entryName;
	}
}
